package com.cjm.jvmcollectors;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class StremDemo {
    /**
     * List 与 int 互相转换
     */
    @Test
    public void test01() {
        int[] array = new int[10];
        Arrays.fill(array, 10);
        Arrays.stream(array).boxed().forEach(System.out::println);

        System.err.println("=============================1");

        Arrays.fill(array, 3, 6, 9);
        Arrays.stream(array).boxed().forEach(System.out::println);

        System.err.println("=============================2");

        List<Integer> collect = Arrays.stream(array).boxed().collect(Collectors.toList());
        int[] array1 = collect.stream().mapToInt(Integer::intValue).toArray();
        for (int i : array1) {
            System.err.println(i);
        }
    }

    static class Student {
        private int id;
        private String name;
        private String score;
        private int classNo;

        public Student(int id, String name, String score, int classNo) {
            this.id = id;
            this.name = name;
            this.score = score;
            this.classNo = classNo;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getScore() {
            return score;
        }

        public void setScore(String score) {
            this.score = score;
        }

        public int getClassNo() {
            return classNo;
        }

        public void setClassNo(int classNo) {
            this.classNo = classNo;
        }

        @Override
        public String toString() {
            return "id=" + id + ", name=" + name + ", score=" + score + ", classNo=" + classNo;
        }
    }

    private static List<String> simpleList = new ArrayList<>();
    private static List<Student> normalList = new ArrayList<>();

    @BeforeEach
    public void test() {
        simpleList.add("apple");
        simpleList.add("apple");
        simpleList.add("banana");
        simpleList.add("orange");

        normalList.add(new Student(1, "Emma", "A", 701));
        normalList.add(new Student(2, "Larissa", "S", 701));
        normalList.add(new Student(3, "Sophia", "B", 701));
        normalList.add(new Student(4, "Ashley", "B", 702));
        normalList.add(new Student(5, "May", "C", 702));
        normalList.add(new Student(6, "Hailey", "D", 702));
        normalList.add(new Student(7, "Kelly", "S", 703));
        normalList.add(new Student(8, "Amy", "A", 703));
        normalList.add(new Student(9, "Wesley", "C", 703));
    }

    @Test
    public void test02() {
        simpleList.forEach(System.out::println);
        printLine("1");
        Set<String> simpleSet = new HashSet<>(simpleList);
        simpleSet.forEach(System.out::println);
    }

    @Test
    public void test03() {
        printLine("1");
        normalList.forEach(System.out::println);

        printLine("1");
        normalList.stream().map(Student::getClassNo).collect(Collectors.toSet()).forEach(System.out::println);

        printLine("1");
        normalList.stream().map(Student::getName).collect(Collectors.toList()).forEach(System.out::println);
    }

    @Test
    public void test04() {
        normalList.stream().collect(Collectors.toMap(Student::getId, b -> b)).forEach((a, b) -> System.out.println(a + " -> " + b.toString()));
    }

    @Test
    public void test05() {
        printLine("原始数据");
        List<Student> students = new ArrayList<>(normalList);
        students.forEach(System.out::println);

        printLine("List转Map， 重复Key只保留前者");
        students.stream().collect(Collectors.toMap(Student::getClassNo, s -> s, (s1, s2) -> s1)).forEach((a, b) -> System.out.println(a + " -> " + b.toString()));
        printLine("第二种方式");
        students.stream().collect(Collectors.toMap(Student::getClassNo, s -> s, (s1, s2) -> s2)).forEach((a, b) -> System.out.println(a + " -> " + b.toString()));

        printLine("List转Map， 重复的key， 收集为一个List");
        students.stream().collect(Collectors.groupingBy(Student::getClassNo)).forEach((a, b) -> System.out.println(a + " ->;; " + b.toString()));
        printLine("第二种方式");
        students.stream().collect(Collectors.toMap(Student::getClassNo, ss -> {
            List<Student> ll = new ArrayList<>();
            ll.add(ss);
            return ll;
        }, (List<Student> s1, List<Student> s2) -> {
            s1.addAll(s2);
            return s1;
        })).forEach((a, b) -> System.out.println(a + " ->;; " + b.toString()));
    }

    @Test
    public void test06() {
        List<Student> students = new ArrayList<>(normalList);
        printLine("先按分数分组");
        Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getScore));
        printLine("Map转List student, 使用flatMap");
        collect.entrySet().stream()
                .flatMap(map -> map.getValue().stream()).collect(Collectors.toList())
                .forEach(System.out::println);
        printLine("直接取values");
        collect.values().forEach(System.out::println);
    }

    @Test
    public void test07() {
        List<Student> students = new ArrayList<>(normalList);
        printLine("分组");
        students.stream().collect(Collectors.groupingBy(Student::getScore)).forEach((score, ss) -> System.out.println(score + ":::" + ss));
        printLine("按多个属性分组");
        students.stream().
                collect(
                        Collectors.groupingBy(e -> e.getClassNo() + "_" + e.getScore()))
                .forEach((learn, ss) -> System.out.println(learn + "::" + ss));
    }

    private static AtomicInteger lineNums = new AtomicInteger();

    private static void printLine(String msg) {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.err.println("===============================> " + lineNums.getAndAdd(1) + ";msg = " + msg);
    }
}
